package notification

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"strings"
	"time"

	"health-check/internal/config"
	"health-check/internal/identity"
	"health-check/internal/logger"

	"github.com/go-resty/resty/v2"
)

// FeishuNotifier 飞书通知器
type FeishuNotifier struct {
	webhookURL    string
	secret        string
	enabled       bool
	client        *resty.Client
	smartNotifier *SmartNotifier
	useCard       bool // 是否使用卡片消息
}

// FeishuMessage 飞书消息结构
type FeishuMessage struct {
	MsgType string `json:"msg_type"`
	Content struct {
		Text string `json:"text"`
	} `json:"content"`
	Timestamp string `json:"timestamp,omitempty"`
	Sign      string `json:"sign,omitempty"`
}

// NewFeishuNotifier 创建飞书通知器
func NewFeishuNotifier(cfg *config.FeishuConfig) *FeishuNotifier {
	notifier := &FeishuNotifier{
		webhookURL: cfg.WebhookURL,
		secret:     cfg.Secret,
		enabled:    cfg.Enabled,
		client:     resty.New().SetTimeout(10 * time.Second),
		useCard:    cfg.UseCard,
	}

	// 如果启用智能通知，创建智能通知器
	if cfg.SmartNotify {
		notifier.smartNotifier = NewSmartNotifier(*cfg)
	}

	return notifier
}

// SendMessage 发送消息
func (fn *FeishuNotifier) SendMessage(title, content string) error {
	// 添加panic恢复
	defer func() {
		if r := recover(); r != nil {
			logger.Errorf("发送飞书消息时发生panic: %v", r)
		}
	}()

	if !fn.enabled {
		return nil
	}

	message := FeishuMessage{
		MsgType: "text",
		Content: struct {
			Text string `json:"text"`
		}{
			Text: fmt.Sprintf("%s\n%s", title, content),
		},
	}

	// 如果有签名密钥，添加签名
	if fn.secret != "" {
		timestamp := fmt.Sprintf("%d", time.Now().Unix())
		message.Timestamp = timestamp
		message.Sign = fn.generateSign(timestamp)
	}

	resp, err := fn.client.R().
		SetHeader("Content-Type", "application/json").
		SetBody(message).
		Post(fn.webhookURL)

	if err != nil {
		logger.Errorf("发送飞书消息失败: %v", err)
		return err
	}

	if resp.StatusCode() != 200 {
		logger.Errorf("发送飞书消息失败，状态码: %d, 响应: %s", resp.StatusCode(), resp.String())
		return fmt.Errorf("发送飞书消息失败，状态码: %d", resp.StatusCode())
	}

	logger.Infof("飞书消息发送成功: %s", title)
	return nil
}

// sendCardMessage 发送卡片消息
func (fn *FeishuNotifier) sendCardMessage(card *FeishuCardMessage) error {
	if !fn.enabled {
		return nil
	}

	// 转换为JSON
	jsonData, err := card.ToJSON()
	if err != nil {
		return fmt.Errorf("序列化卡片消息失败: %v", err)
	}

	// 发送请求（带重试）
	var resp *resty.Response

	for attempt := 1; attempt <= 3; attempt++ {
		resp, err = fn.client.R().
			SetHeader("Content-Type", "application/json").
			SetBody(jsonData).
			Post(fn.webhookURL)

		if err != nil {
			logger.Warnf("飞书卡片消息发送失败 (尝试 %d/3): %v", attempt, err)
			if attempt < 3 {
				time.Sleep(time.Duration(attempt) * time.Second) // 递增延迟
				continue
			}
			return fmt.Errorf("发送卡片消息失败: %v", err)
		}

		if resp.StatusCode() == 200 {
			break // 成功
		}

		logger.Warnf("飞书卡片消息发送失败 (尝试 %d/3)，状态码: %d, 响应: %s", attempt, resp.StatusCode(), resp.String())
		if attempt < 3 {
			time.Sleep(time.Duration(attempt) * time.Second) // 递增延迟
			continue
		}
		return fmt.Errorf("发送卡片消息失败，状态码: %d", resp.StatusCode())
	}

	logger.Infof("飞书卡片消息发送成功")
	return nil
}

// SendProcessAlert 发送进程告警
func (fn *FeishuNotifier) SendProcessAlert(processName, status, message string) error {
	serverID := identity.GetServerID()

	// 如果启用智能通知，检查是否应该发送通知
	if fn.smartNotifier != nil {
		if !fn.smartNotifier.ShouldNotify(MessageTypeProcessAlert, serverID, processName) {
			logger.Debugf("进程告警被智能通知过滤: %s", processName)
			return nil
		}

		// 添加到聚合器
		aggregatedMsg := fn.smartNotifier.AddMessage(MessageTypeProcessAlert, serverID, processName, message, status)

		if fn.useCard {
			// 使用卡片消息
			card := aggregatedMsg.GetCardMessage()
			return fn.sendCardMessage(card)
		} else {
			// 使用文本消息
			title := fmt.Sprintf("🚨 进程监控告警 - %s", processName)
			content := fmt.Sprintf("服务器: %s\n进程名称: %s\n状态: %s\n详情: %s\n时间: %s",
				serverID, processName, status, message, time.Now().Format("2006-01-02 15:04:05"))
			return fn.SendMessage(title, content)
		}
	} else {
		// 不使用智能通知，直接发送
		if fn.useCard {
			// 使用卡片消息
			card := CreateProcessAlertCard(processName, status, message, serverID)
			return fn.sendCardMessage(card)
		} else {
			// 使用文本消息
			title := fmt.Sprintf("🚨 进程监控告警 - %s", processName)
			content := fmt.Sprintf("服务器: %s\n进程名称: %s\n状态: %s\n详情: %s\n时间: %s",
				serverID, processName, status, message, time.Now().Format("2006-01-02 15:04:05"))
			return fn.SendMessage(title, content)
		}
	}
}

// SendProcessRestartAlert 发送进程重启告警
func (fn *FeishuNotifier) SendProcessRestartAlert(processName string, restartCount int, message string) error {
	serverID := identity.GetServerID()

	// 根据消息内容判断是告警还是恢复通知
	var messageType MessageType
	var title string
	if strings.Contains(message, "重启成功") || strings.Contains(message, "已恢复") {
		messageType = MessageTypeProcessRecovery
		title = fmt.Sprintf("✅ 进程恢复通知 - %s", processName)
	} else {
		messageType = MessageTypeProcessRestart
		title = fmt.Sprintf("🔄 进程重启告警 - %s", processName)
	}

	// 检查是否应该发送通知
	if !fn.smartNotifier.ShouldNotify(messageType, serverID, processName) {
		logger.Debugf("进程通知被智能通知过滤: %s", processName)
		return nil
	}

	// 添加到聚合器
	aggregatedMsg := fn.smartNotifier.AddMessage(messageType, serverID, processName, message, fmt.Sprintf("重启次数: %d", restartCount))

	if fn.useCard {
		// 使用卡片消息
		card := aggregatedMsg.GetCardMessage()
		return fn.sendCardMessage(card)
	} else {
		// 使用文本消息
		var content string
		if restartCount > 0 {
			content = fmt.Sprintf("服务器: %s\n进程名称: %s\n重启次数: %d\n详情: %s\n时间: %s",
				serverID, processName, restartCount, message, time.Now().Format("2006-01-02 15:04:05"))
		} else {
			content = fmt.Sprintf("服务器: %s\n进程名称: %s\n详情: %s\n时间: %s",
				serverID, processName, message, time.Now().Format("2006-01-02 15:04:05"))
		}
		return fn.SendMessage(title, content)
	}
}

// SendProcessRecoveryAlert 发送进程恢复告警
func (fn *FeishuNotifier) SendProcessRecoveryAlert(processName string) error {
	serverID := identity.GetServerID()

	// 检查是否应该发送通知
	if !fn.smartNotifier.ShouldNotify(MessageTypeProcessRecovery, serverID, processName) {
		logger.Debugf("进程恢复通知被智能通知过滤: %s", processName)
		return nil
	}

	// 添加到聚合器
	aggregatedMsg := fn.smartNotifier.AddMessage(MessageTypeProcessRecovery, serverID, processName, "进程已恢复", "已恢复")

	if fn.useCard {
		// 使用卡片消息
		card := aggregatedMsg.GetCardMessage()
		return fn.sendCardMessage(card)
	} else {
		// 使用文本消息
		title := fmt.Sprintf("✅ 进程恢复通知 - %s", processName)
		content := fmt.Sprintf("服务器: %s\n进程名称: %s\n状态: 已恢复\n时间: %s",
			serverID, processName, time.Now().Format("2006-01-02 15:04:05"))
		return fn.SendMessage(title, content)
	}
}

// SendSystemAlert 发送系统告警
func (fn *FeishuNotifier) SendSystemAlert(title, message string) error {
	serverID := identity.GetServerID()

	// 检查是否应该发送通知
	if !fn.smartNotifier.ShouldNotify(MessageTypeSystemAlert, serverID, title) {
		logger.Debugf("系统告警被智能通知过滤: %s", title)
		return nil
	}

	// 添加到聚合器
	aggregatedMsg := fn.smartNotifier.AddMessage(MessageTypeSystemAlert, serverID, title, message, "系统告警")

	if fn.useCard {
		// 使用卡片消息
		card := aggregatedMsg.GetCardMessage()
		return fn.sendCardMessage(card)
	} else {
		// 使用文本消息
		fullTitle := fmt.Sprintf("⚠️ 系统告警 - %s", title)
		content := fmt.Sprintf("服务器: %s\n%s\n时间: %s", serverID, message, time.Now().Format("2006-01-02 15:04:05"))
		return fn.SendMessage(fullTitle, content)
	}
}

// generateSign 生成签名
func (fn *FeishuNotifier) generateSign(timestamp string) string {
	stringToSign := timestamp + "\n" + fn.secret
	h := hmac.New(sha256.New, []byte(fn.secret))
	h.Write([]byte(stringToSign))
	return base64.StdEncoding.EncodeToString(h.Sum(nil))
}

// IsEnabled 检查是否启用
func (fn *FeishuNotifier) IsEnabled() bool {
	return fn.enabled
}

// TestConnection 测试连接
func (fn *FeishuNotifier) TestConnection() error {
	if !fn.enabled {
		return fmt.Errorf("飞书通知未启用")
	}

	serverID := identity.GetServerID()

	if fn.useCard {
		// 使用卡片消息
		card := CreateTestCard(serverID)
		return fn.sendCardMessage(card)
	} else {
		// 使用文本消息
		testMessage := "🧪 飞书通知测试消息"
		content := fmt.Sprintf("这是一条测试消息，用于验证飞书通知配置是否正确。\n服务器: %s\n时间: %s",
			serverID, time.Now().Format("2006-01-02 15:04:05"))
		return fn.SendMessage(testMessage, content)
	}
}
